#ifndef prs_FrmDefTemplate_H
#define prs_FrmDefTemplate_H

#include "prs_FrmRules.h"
#include "prs_FrmFunc.h"
#include "prs_FrmLinkAttr.h"
#include "prs_FrmValueRule.h"

namespace prs {

///////////////////////////////////////////////////////////////////////////////

struct TNodeDefTemplateParam : public TNodeFrm
{
  DECLARE_ClientNode()
  //
  TAttrNodeType<nodeType_DefTemplateParam> NodeType;
  TAttrId Id;
  TAttrPointerNodeOwner<attrName_DefValue,TFrmValue*> DefValue;
  TAttrNodeArray<attrName_LinkAttr,TNodeFrmLinkAttrArray> LinkAttr;
  //
  TNodeDefTemplateParam() : NodeType(this),Id(this),DefValue(this),LinkAttr(this) {}
  //
  bool AddLinkAttr(
    TAttr *Attr,
    TFrmValue &ValueType,
    svl::TString &OutError = svl::TString()
  );
  bool AddLinkControls(
    TFrmControlsValue *ControlsValue,
    svl::TString &OutError = svl::TString()
  );
};

///////////////////////////////////////////////////////////////////////////////

struct TNodeDefTemplateParams : public TNodeArrayT<TNodeDefTemplateParam>
{
};

///////////////////////////////////////////////////////////////////////////////

struct TNodeDefTemplateBody : public TNodeFrm
{
  DECLARE_ClientNode()
  TAttrNodeType<nodeType_DefTemplateBody> NodeType;
  //
  TNodeDefTemplateBody() : NodeType(this) {}
};

///////////////////////////////////////////////////////////////////////////////

struct TNodeDefTemplate : public TNodeFrm
{
  DECLARE_ClientNode()
  //
  TAttrNodeType<nodeType_DefTemplate> NodeType;
  TAttrId Id;
  TAttrNodeArray<attrName_Params,TNodeDefTemplateParams> Params;
  TAttrNodeObject<attrName_Body,TNodeDefTemplateBody> Body;
  //
  TNodeDefTemplate() : NodeType(this),Id(this),Params(this),Body(this) {}
  //
  TNodeDefTemplateParam *SearchParamById(char *Id);
  //
  static TNodeDefTemplate *SearchDefTemplateById(TNode *FromChild,char *Id);
  static TNodeDefTemplateParam *SearchParamById(TNode *FromChild,char *Id);
  //
  static bool AddLinkAttrByParamId(
    TAttr *Attr,
    TFrmValue &ValueType,
    svl::TString &ParamId,
    svl::TString &OutError
  );

/********
  bool FSetParamString(TRuleSetAttrValue::TFuncValueIdentParams &Params) {
    return TNodeDefTemplate::AddLinkAttrByParamId(Params.Attr,TFrmStringValue(),Params.Ident,Params.OutError);
  }
  template<class ParamType> static TFuncValueIdent FSetParam(
    TRuleSetAttrValue::TFuncValueIdentParams &Params,
    ParamType &PT
  ){
    return AddLinkAttrByParamId(Params.Attr,PT,Params.Ident,Params.OutError);
  }
***************/  
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

struct TRuleDefTemplate : public snt::TRule
{
  TRuleDefTemplate(
    snt::text::TContext &Context,
    svl::TVariant &VParentNode,
    TRuleFrmChildrenBase &RFrmChildren,
    TRuleFrmValue &RFrmValue
  );
  
private:
  TNodeDefTemplate *GetNodeDefTemplate() { return dynamic_cast<TNodeDefTemplate*>(vParentNode.Pointer());}
  //
  bool FNewDefTemplate(snt::text::TIdent::TFuncClosureDoEntryParams &Params);
  void FNewNodeDefTemplateParam(snt::TParams &Params);
  bool FSetParamId(snt::text::TIdent::TFuncClosureDoEntryParams &Params);
  void FSetBody(snt::TParams &Params) { vParentNode = &GetNodeDefTemplate()->Body.Value;}
  //
  svl::TVariant &vParentNode;
  snt::TRule  RParams,RParam,RBody;
  snt::TAlter AParams;
};

///////////////////////////////////////////////////////////////////////////////
}

#endif
